#include "stdafx.h"

#include "globals.h"
#include "FilterControl.H"


const int MAX_VOLUMES = 16;

static LONG s_volume_values[MAX_VOLUMES] = { // increment 6db..
	-10000, -5754, -3311, -1905, -1300, 
	-1000, -900, -800, -700, -600,
	-500, -400, -300, -200, -100, 
	0
};

CFilterControl cNewFilterCtrl;

CFilterControl::CFilterControl()
{
	mpGraph = NULL;
	mIsRunning=false;
}

CFilterControl::~CFilterControl()
{
}

BOOL CFilterControl::CheckCoCreateInstance(HRESULT &hr, REFCLSID rclsid, REFIID riid, LPVOID* ppv, LPCTSTR pszErrorMessage)
{
	if( SUCCEEDED(hr) )
	{
		hr=::CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, riid, ppv);
		if( SUCCEEDED(hr) )
		{
			return TRUE;
		}
		else
		{
			TCHAR tmp[256];
			::wsprintf(tmp, TEXT("[FAIL]CoCreateInstance(%x%x%x%x), %s"), ((DWORD *)&rclsid)[0], ((DWORD *)&rclsid)[1], ((DWORD *)&rclsid)[2], ((DWORD *)&rclsid)[3], pszErrorMessage);
			
			::MessageBox(NULL, tmp, TEXT("TCCAMManger"), 0);
			::printf("[FAIL]CoCreateInstance(%x%x%x%x) hr=%x\r\n", ((DWORD *)&rclsid)[0], ((DWORD *)&rclsid)[1], ((DWORD *)&rclsid)[2], ((DWORD *)&rclsid)[3], hr);
		}
	}

	return FALSE;
}

int CFilterControl::CreateFilterGraph(void)
{
	printf("[CFilterControl::CreateFilterGraph]\n");

	HRESULT hr=S_OK;

	CheckCoCreateInstance(hr, CLSID_FilterGraph, IID_IGraphBuilder, (void **)&mpGraph, TEXT("CLSID_FilterGraph fail"));	

	if( SUCCEEDED(hr) )
	{
		// DEQ Filter Create
		hr = CoCreateInstance((REFCLSID)CLSID_TCCDEQ, NULL, CLSCTX_INPROC, (REFIID)IID_IBaseFilter,
						 (void **)&m_pDEQFilter);
		// DEQ Filter Add
		if(SUCCEEDED(hr))
			hr = mpGraph->AddFilter(m_pDEQFilter,L"TCC DEQ Filter");
			// DEQ Filter Initial Setting
		if (hr==S_OK)
		{
			ITCCDEQINTERFACE* pIDEQ=NULL;
			DEQDynamicFlag flag;
			flag.OnOff=FALSE; 	

			hr = m_pDEQFilter->QueryInterface(CLSID_TCCDEQINTERFACE, (void**)&pIDEQ);
    		if (SUCCEEDED(hr) && pIDEQ)
			{
				pIDEQ->SetEQDynamicFlag(flag);
			}
    		SAFE_RELEASE(pIDEQ);
		}
		else
		{
			printf("HR=%08X\n",hr);
		}
		hr=S_OK;	

		return 1;
	}
	
	return 0;	
}


void CFilterControl::DestroyFilterGraph(void)
{
	printf("[DestroyFilterGraph]Start\n");
	
	mpGraph->AddRef();
	int iRetFilterValue=mpGraph->Release();
	if(iRetFilterValue>1)
	{
		printf("\t\t DestroyFilterGraph::RemindRef=%d\n",iRetFilterValue);
	}

	SAFE_RELEASE(mpGraph);	

	printf("[DestroyFilterGraph]End\n");
}


////////////////////////////////////////////////////////////////////////////////////////////////////

BOOL CFilterControl::RunGraph()
{
	if (!mpGraph)
		return FALSE;

	IMediaControl* p_mc = NULL;

	HRESULT hr = mpGraph->QueryInterface(IID_IMediaControl, (void **)&p_mc);
	if (hr == S_OK)
	{
		hr = p_mc->Run();
		mIsRunning = TRUE;
		if (FAILED(hr))
			printf("Fail : RunGraph(ret=0x%x)\r\n", hr);
		SAFE_RELEASE(p_mc);
	}
	return SUCCEEDED(hr);
}

//
// Stop the graph
// -- (return ) TRUE, if successful / FALSE, otherwise
//
BOOL CFilterControl::StopGraph()
{
	if (!mpGraph)
		return FALSE;
	
//	if (!IsGraphStopped()) 
	if (mIsRunning)
	{
		IMediaControl* p_mc = NULL;
		HRESULT hr = mpGraph->QueryInterface(IID_IMediaControl, (void **)&p_mc);
		if (hr == S_OK)
		{
			hr = p_mc->Stop();
			mIsRunning = FALSE;
			if (FAILED(hr))
				printf("Fail : StopGraph 0x%x\n", hr);
			else
				printf("Succeed to stop Graph\n");
			SAFE_RELEASE(p_mc);
		}
		else
		{
			printf("Fail : mpGraph->QueryInterface(IID_IMediaControl)\n");
		}
		return SUCCEEDED(hr);
	}
	else
		printf("StopGraph(SKIPPED) since it's already stopped\r\n");

	return FALSE;
}

//
// Pause the graph
// -- (return ) TRUE, if successful / FALSE, otherwise
//
BOOL CFilterControl::PauseGraph()
{
	if (!mpGraph)
		return FALSE;
	
	IMediaControl* p_mc = NULL;
	HRESULT hr = mpGraph->QueryInterface(IID_IMediaControl, (void **)&p_mc);
	if( hr==S_OK )
	{
		hr = p_mc->Pause();
		mIsRunning = FALSE;
		if (hr != S_OK)
			printf("Fail : StopGraph(ret=0x%x)\r\n", hr);
		SAFE_RELEASE(p_mc);
	}

	return SUCCEEDED(hr);
}

////////////////////////////////////////////////////////////////////////////////////////////////////



int CFilterControl::CreateFilterForPlaying(TCHAR *FileName)
{
	printf("[CFilterControl::CreateFilterForPlaying]\n");

	HRESULT hr=S_OK;

//	DestroyFilterGraph();

	CreateFilterGraph();

	hr = mpGraph->RenderFile(FileName,NULL);

	if( SUCCEEDED(hr) )
	{
		printf("[CFilterControl::CreateFilterForPlaying]OK\n");
		return 1;
	}
	
	return 0;	
}

void CFilterControl::DeleteFiltersForPlaying(void)
{
   if (!mpGraph)
      return;

   // -- Delete other filters
   HRESULT        hr = E_FAIL;
   FILTER_INFO    fiInfo;
   IEnumFilters*  pFilterEnum = NULL;

   hr = mpGraph->EnumFilters(&pFilterEnum);
	if (FAILED(hr))
      return;

   int nFilterCount= 0;
   int nPos		= 0;
   
  SAFE_RELEASE(m_pDEQFilter);

   while (S_OK == pFilterEnum->Skip(1)) {
      nFilterCount++;
   }
   
   IBaseFilter **ppFilters = reinterpret_cast<IBaseFilter **> (_alloca(sizeof(IBaseFilter*)*nFilterCount ) );
   pFilterEnum->Reset();
   
   while (S_OK == pFilterEnum->Next(1, &(ppFilters[nPos++]), NULL));
   SAFE_RELEASE(pFilterEnum);
   
   for (nPos = 0; nPos < nFilterCount; nPos++) {
      ppFilters[nPos]->QueryFilterInfo(&fiInfo);
      char name[80];
      WideCharToMultiByte(CP_ACP, 0, fiInfo.achName, -1, name, 80, NULL, NULL);
      printf("DeleteFilters() - %s\r\n", name);
      
      ULONG r1=ppFilters[nPos]->AddRef();
      ULONG r2=ppFilters[nPos]->Release();
      
	  fiInfo.pGraph->Release();
      
	  mpGraph->RemoveFilter(ppFilters[nPos]);
      SAFE_RELEASE(ppFilters[nPos]);
   }
}

BOOL CFilterControl::GetPlayDuration(double *duration)
{
	if (!mpGraph)
		return FALSE;
	
	IMediaControl* p_mc = NULL;
	HRESULT hr = mpGraph->QueryInterface(IID_IMediaControl, (void **)&p_mc);
	if( hr==S_OK )
	{
		IMediaPosition *pMediaPosition;

		p_mc->QueryInterface(IID_IMediaPosition,(void**)&pMediaPosition);

		pMediaPosition->get_Duration(duration);		

		SAFE_RELEASE(pMediaPosition);
		SAFE_RELEASE(p_mc);
	}

	return SUCCEEDED(hr);
}

BOOL CFilterControl::GetCurrentPlayTime(double *pos)
{
	if (!mpGraph)
		return FALSE;
	
	IMediaControl* p_mc = NULL;
	HRESULT hr = mpGraph->QueryInterface(IID_IMediaControl, (void **)&p_mc);
	if( hr==S_OK )
	{
		IMediaPosition *pMediaPosition;

		p_mc->QueryInterface(IID_IMediaPosition,(void**)&pMediaPosition);
		
		pMediaPosition->get_CurrentPosition(pos);

		SAFE_RELEASE(pMediaPosition);
		SAFE_RELEASE(p_mc);
	}

	return SUCCEEDED(hr);
}

BOOL CFilterControl::SetCurrentPlayTime(double pos)
{
	if (!mpGraph)
		return FALSE;
	
	IMediaControl* p_mc = NULL;
	HRESULT hr = mpGraph->QueryInterface(IID_IMediaControl, (void **)&p_mc);
	if( hr==S_OK )
	{
		IMediaPosition *pMediaPosition;

		p_mc->QueryInterface(IID_IMediaPosition,(void**)&pMediaPosition);
		
		pMediaPosition->put_CurrentPosition(pos);

		SAFE_RELEASE(pMediaPosition);
		SAFE_RELEASE(p_mc);
	}

	return SUCCEEDED(hr);
}

void CFilterControl::SetDEQMode(DEQDynamicFlag Newflag)
{
	if(m_pDEQFilter)
	{			
		ITCCDEQINTERFACE* pIControl = NULL;

		HRESULT hr = m_pDEQFilter->QueryInterface(CLSID_TCCDEQINTERFACE, (void**)&pIControl);	   
		if (SUCCEEDED(hr) && pIControl)
        {
			DEQDynamicFlag dflag;

			memcpy((void*)&dflag,(void*)&Newflag,sizeof(DEQDynamicFlag));

			pIControl->SetEQDynamicFlag(dflag);			

			SAFE_RELEASE(pIControl);
		}
	}
}

void CFilterControl::GetPWSBand(int *pPWSBand,int MaxBandNum)
{
	if(m_pDEQFilter)
	{			
		ITCCPWSINTERFACE* pIControl = NULL;

		HRESULT hr = m_pDEQFilter->QueryInterface(CLSID_TCCPWSINTERFACE, (void**)&pIControl);	   
		if (SUCCEEDED(hr) && pIControl)
        {
			pIControl->GetPWSBand(pPWSBand,MaxBandNum);			

			SAFE_RELEASE(pIControl);
		}
	}
}


void CFilterControl::SetPWSOnOff(BOOL bOnOff)
{
	if(m_pDEQFilter)
	{			
		ITCCPWSINTERFACE* pIControl = NULL;

		HRESULT hr = m_pDEQFilter->QueryInterface(CLSID_TCCPWSINTERFACE, (void**)&pIControl);	   
		if (SUCCEEDED(hr) && pIControl)
        {
			pIControl->SetPWSOnOff(bOnOff);			

			SAFE_RELEASE(pIControl);
		}
	}
}


BOOL CFilterControl::SetAudioVolume(unsigned int AudioVolume)
{
	if (AudioVolume > MAX_VOLUMES)
		AudioVolume = MAX_VOLUMES;
	
	LONG volume = s_volume_values[AudioVolume];

	if (!mpGraph)
		return FALSE;

	IBasicAudio* p_basic_audio = NULL;
	HRESULT hr = mpGraph->QueryInterface(IID_IBasicAudio, (void**)&p_basic_audio);
	if(SUCCEEDED(hr))
	{
		p_basic_audio->put_Volume(volume);
	}
	SAFE_RELEASE(p_basic_audio);	
	return SUCCEEDED(hr);
}

BOOL CFilterControl::GetAudioVolume(unsigned int* pAudioVolume)
{
	if (!mpGraph)
		return FALSE;
		
	LONG volume = 0;
	
	IBasicAudio* p_basic_audio = NULL;
	HRESULT hr = mpGraph->QueryInterface(IID_IBasicAudio, (void**)&p_basic_audio);
	if(SUCCEEDED(hr))
	{
		p_basic_audio->get_Volume(&volume);
	}
	SAFE_RELEASE(p_basic_audio);

	for(int i=0; i<MAX_VOLUMES; i++)
	{
		if(volume <= s_volume_values[i])
		{
			*pAudioVolume = i;
			break;
		}
	}
	return SUCCEEDED(hr);
}